#pragma once
#ifndef EVENTLOOP_H
#define EVENTLOOP_H
#include "NonCopyable.h"
#include <vector>
#include <atomic>
#include <memory>
#include <mutex>
#include <functional>
#include "CurrentThread.h"
#include "TimeStamp.h"
namespace mymuduo {

class Channel;
class Poller;

// 事件循环类，主要包含了两个大模块 Channel Poller（epoll 的抽象）
// 相当于 Reactor 的角色
class EventLoop : NonCopyable {
public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    // 开启和结束事件循环
    void loop();
    void quit();

    TimeStamp poolReturnTime() const {return pollReturnTime_;}

    // 在当前 loop 中执行 cb
    void runInLoop(Functor cb);
    // 把 cb 放入队列中，唤醒 loop 所在的线程执行 cb
    void queueInLoop(Functor cb);
    
    // 唤醒 loop 所在的线程
    void wakeup();

    // EventLoop 的方法，调用的就是 Poller 的方法
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel* channel);

    // 判断 EventLoop 对象是否在自己的线程里面
    bool isInLoopThread() const {return threadId_ == currentthread::tid();}
private:
    void handleRead(); // 处理 wakeup
    void doPendingFunctors(); // 执行回调

    using ChannelList = std::vector<Channel*>;

    Poller* poller_;
    std::atomic_bool looping_; // 原子操作
    std::atomic_bool quit_; // 标记是否退出事件循环
    const pid_t threadId_; // 记录当前 loop 所在线程的 id
    TimeStamp pollReturnTime_; // poller 返回发生事件的 channel 的时间点
    int wakeupFd_; // 主要作用：当 mainloop 获取一个新用户的 channel，通过轮询算法选择一个 subloop，通过该成员唤醒 subloop 处理 channel
    std::unique_ptr<Channel> wakeupChannel_; 
    ChannelList activeChannels_;
    // Channel* currentActiveChannel_; // 断言使用，精简版本不需要

    std::atomic_bool callingPendingFunctors_; // 标识当前 loop 是否有需要执行的回调操作
    std::mutex mutex_; // 通过锁保护回调操作
    std::vector<Functor> pendingFunctors_; // 存储 loop 需要在执行的所有回调操作
}; 

}

#endif